package represent.type;

public class FloatType implements Type {

	private Float val;

	public FloatType(double v) {
		val = new Double(v).floatValue();
	}

	public FloatType(float v) {
		val = v;
	}

	public FloatType(int v) {
		val = new Integer(v).floatValue();
	}

	public FloatType(Type v) {
		Object jval = v.asJavaVal();
		if(v instanceof IntType)
			val = ((Integer)jval).floatValue();
		else if(v instanceof FloatType)
			val = (Float) jval;
		else if(v instanceof DecimalType)
			val = ((Double)jval).floatValue();
		else
			throw new Error("Cannot convert " + jval + " to float.");
	}

	public FloatType(String s) {
		val = new Float(s);
	}

	public FloatType(IntType c) {
		val = ((Integer) c.asJavaVal()).floatValue();
	}

	public Type getDecFromString(String s) {
		Integer i = null;
		Double f = null;
		try {
			i = new Integer(s);
		} catch(Exception e1) {
			try {
				f = new Double(s);
			} catch(Exception e2) {
				throw new Error("Cannot conver " + s + " to number");
			}
		}
		if(i != null)
			return new IntType(i);
		else
			return new DecimalType(f);
	}

	public int hashCode() {
		return val.hashCode();
	}

	public String toString() {
		return val.toString();
	}

	public Object asJavaVal() {
		return val;
	}

	public Type divide(Type c) {
		if (c instanceof StringType) {
			String v = ((StringType) c).asJavaVal();
			return divide(getDecFromString(v));
		} else if(c instanceof IntType) {
			FloatType rhv = new FloatType((IntType) c);
			return new FloatType(val / rhv.val);
		}
		else if(c instanceof FloatType)
			return new FloatType(val / (Float) c.asJavaVal());
		else if(c instanceof DecimalType) {
			DecimalType lhv = new DecimalType(this);
			DecimalType rhv = (DecimalType) c;
			return lhv.divide(rhv);
		}
		else throw new Error("Unconsistent types.");
	}

	public String getType() {
		return "float";
	}

	public Type minus(Type c) {
		if (c instanceof StringType) {
			String v = ((StringType) c).asJavaVal();
			return minus(getDecFromString(v));
		} else if(c instanceof IntType) {
			FloatType rhv = new FloatType((IntType) c);
			return new FloatType(val - rhv.val);
		}
		else if(c instanceof FloatType)
			return new FloatType(val - (Float) c.asJavaVal());
		else if(c instanceof DecimalType) {
			DecimalType lhv = new DecimalType(this);
			DecimalType rhv = (DecimalType) c;
			return lhv.minus(rhv);
		}
		else throw new Error("Unconsistent types.");
	}

	public Type mod(Type c) {
		throw new Error("Type decimal should not do mod.");
	}

	public Type mult(Type c) {
		if (c instanceof StringType) {
			String v = ((StringType) c).asJavaVal();
			return mult(getDecFromString(v));
		} else if(c instanceof IntType) {
			FloatType rhv = new FloatType((IntType) c);
			return new FloatType(val * rhv.val);
		}
		else if(c instanceof FloatType)
			return new FloatType(val * (Float) c.asJavaVal());
		else if(c instanceof DecimalType) {
			DecimalType lhv = new DecimalType(this);
			DecimalType rhv = (DecimalType) c;
			return lhv.mult(rhv);
		}
		else throw new Error("Unconsistent types.");
	}

	public Type plus(Type c) {
		if(c instanceof IntType) {
			FloatType rhv = new FloatType((IntType) c);
			return new FloatType(val + rhv.val);
		}
		else if(c instanceof FloatType)
			return new FloatType(val + (Float) c.asJavaVal());
		else if(c instanceof DecimalType) {
			DecimalType lhv = new DecimalType(this);
			DecimalType rhv = (DecimalType) c;
			return lhv.plus(rhv);
		}
		else throw new Error("Unconsistent types.");
	}


	public int compareTo(Type c) {
		if (c instanceof StringType) {
			String v = ((StringType) c).asJavaVal();
			return compareTo(getDecFromString(v));
		} else if(c instanceof IntType) {
			FloatType fv = new FloatType((IntType) c);
			return val.compareTo(fv.val);
		}
		else if(c instanceof FloatType) {
			return val.compareTo((Float) ((FloatType) c).asJavaVal());
		}
		else if(c instanceof DecimalType) {
			DecimalType lhv = new DecimalType(this);
			DecimalType rhv = (DecimalType) c;
			return lhv.compareTo(rhv);
		}
		else throw new Error("Cannot convert type.");
	}

	public boolean equals(Object o) {
		if (o instanceof StringType) {
			String v = ((StringType) o).asJavaVal();
			return equals(getDecFromString(v));
		} else if(o instanceof IntType) {
			FloatType fv = new FloatType((IntType) o);
			return val != null && val.equals(fv.val);
		}
		else if(o instanceof FloatType) {
			return val.equals((Float) ((FloatType) o).asJavaVal());
		}
		else if(o instanceof DecimalType) {
			DecimalType lhv = new DecimalType(this);
			DecimalType rhv = (DecimalType) o;
			return lhv.equals(rhv);
		}
		else throw new Error("Cannot convert type.");
	}

	public static int compare(byte[] a, byte[] b) {
		// TODO �Զ���ɷ������
		return 0;
	}

	public static FloatType fromBytes(byte[] bytes) {
		// TODO �Զ���ɷ������
		return null;
	}

	public int TypeToInt() {
		return utils.Constant.FLOAT;
	}
	
	public static int length() {
		return 4;
	}
	
}
